(* Module for evaluating boolean expressions *)

open States;;
open Ast;;

(* Evaluate logical NOT *)
let logicalNot = function
	True -> False
	| False -> True
	;;

(* Test equality of values *)
let equal val1 val2 = if (val1 = val2) then True else False;;

(* Evaluate a conjunction (AND) *)
let conjunction val1 val2 = if ((val1 = val2) && (val1 = True)) then True else False;;

(* Evaluate a disjunction (OR) *)
let disjunction val1 val2 = if ((val1 = True) || (val2 = True)) then True else False;;

(* return True or False given a state and a boolean expression *)
let rec evaluate state = function
	Value(True) -> True
	| Value(False) ->  False
	| Variable(id) ->  getValue state id
	| Not(e) ->  logicalNot (evaluate state e)
	| Equal(e1, e2) -> equal (evaluate state e1) (evaluate state e2)
	| And(e1, e2) -> conjunction (evaluate state e1) (evaluate state e2)
	| Or(e1, e2) -> disjunction (evaluate state e1) (evaluate state e2)
	| Group(e) -> (evaluate state e)
	;;

(* Evaluates a list of expressions, takes a state and a list of the expressions to be evaluated. *)
let rec evaluateList state = function
	| expr :: rest -> (evaluate state expr) :: (evaluateList state rest)
	| [] -> []
	;;
  
(* Evaluates a list of expressions and returns a string with the result separated with comma *)
let rec stringFromExpList state = function (* match expression list *)
	[exp] ->
		let result = evaluate state exp in
		if (result = True) then
			"tt"
		else
			"ff"
	| exp :: exprs -> 
		let rest = stringFromExpList state exprs in
		let result = evaluate state exp in
			if (result = True) then
				"tt, " ^ rest
			else
				"ff, " ^ rest
	| [] -> "" (* not reachable *)
	;;
						